# -*- coding: utf-8 -*-

import sys
import os
import re
from datetime import datetime
import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext
from tkinter.filedialog import askdirectory
from tkinter.filedialog import asksaveasfilename

saveSTDOUT = sys.stdout
saveSTDERR = sys.stderr

class myScrolledText(scrolledtext.ScrolledText):
    def write(self, outStr):
        self.config(state='normal')
        if outStr in ["\n", ""]:
            self.insert('end', outStr)
        else:
            self.insert(
                'end',
                datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " >>> " +
                outStr)
        self.config(state='disabled')
        self.see("end")
        self.master.update()

class App(ttk.Frame):
    #构造函数
    def __init__(self, master=None):
        ttk.Frame.__init__(self, master)
        self.grid()
        self.PROG = tk.IntVar()
        self.PROG.set(0)
        self.createWidgets()
        self.parserEntry.insert(0, "。")
        self.rangeSelector.insert(0, "0:0")

    #浏览按钮动作定义
    def browse_directory(self):
        inputDirectory = askdirectory()
        self.directorySelector.delete(0, 'end')
        self.directorySelector.insert(0, inputDirectory)

    def browse_saveasfile(self):
        outputFile = asksaveasfilename(
            defaultextension='.txt', filetypes=[("CSV File(UTF-8)", ".csv")])
        self.saveasfileSelector.delete(0, 'end')
        self.saveasfileSelector.insert(0, outputFile)

    #初始化控件
    def createWidgets(self):

        self.inputLabel = ttk.Label(self, text="请选择待检索文件目录：")
        self.inputLabel.grid(row=0, sticky='e')
        self.outputLabel = ttk.Label(self, text="请选择输出文件位置：")
        self.outputLabel.grid(row=1, sticky='e')
        self.directorySelector = ttk.Entry(self, width=42)
        self.directorySelector.grid(row=0, column=1, sticky='w')
        self.saveasfileSelector = ttk.Entry(self, width=42)
        self.saveasfileSelector.grid(row=1,column=1, sticky="w")
        self.inputButton = ttk.Button(self, text="浏览", command=self.browse_directory)
        self.inputButton.grid(row=0, column=2, sticky='e')
        self.outputButton = ttk.Button(self, text="浏览", command=self.browse_saveasfile)
        self.outputButton.grid(row=1, column=2, sticky='e')        
        self.parserLabel = ttk.Label(self, text='请输入断句标点，多个符号请用"|"连接：')
        self.parserLabel.grid(row=2, sticky='e')
        self.ruleLabel = ttk.Label(self, text="请输入检索规则：")
        self.ruleLabel.grid(row=4, sticky='e')
        self.parserEntry = ttk.Entry(self, width=55)
        self.parserEntry.grid(row=2, column=1, columnspan=2, sticky='w')
        self.ruleEntry = tk.Text(self, height=10, width=55)
        self.ruleEntry.grid(row=4, column=1, columnspan=2, sticky='w')
        self.rangeLabel = ttk.Label(self, text="请设置前后步长，以英文冒号分隔：")
        self.rangeLabel.grid(row=3, sticky='e')
        self.rangeSelector = ttk.Entry(self, width=55)
        self.rangeSelector.grid(row=3, column=1, columnspan=2, sticky='w')
        self.startButton = ttk.Button(self, text="开始检索", command=self.click)
        self.startButton.grid(row=5, columnspan=3)
        self.consoleText = myScrolledText(self)
        self.consoleText.grid(row=6, columnspan=3)
        self.consoleText.config(state='disabled')
        self.progBar = ttk.Progressbar(self, orient = "horizontal", mode = "determinate",variable=self.PROG, length = 615)
        self.progBar.grid(row=7, columnspan=4)

    def click(self):
        sys.stdout = self.consoleText
        sys.stderr = self.consoleText

        inputDirectory = self.directorySelector.get()
        saveasFile = self.saveasfileSelector.get()
        punc = self.parserEntry.get()
        rule = self.ruleEntry.get("0.0", "end")
        ranges = self.rangeSelector.get()
        backward = int(ranges.split(":")[0])
        forward = int(ranges.split(":")[1])

        self.PROG.set(0)
        self.startButton.config(state="disabled")

        self.main(inputDirectory, saveasFile, punc, rule, backward, forward)

        self.startButton.config(state="normal")

        sys.stdout = saveSTDOUT
        sys.stderr = saveSTDERR


    #定义检索函数1&2&3
    def extract(self, text, regex):  #text为分割后的列表格式文本，rule为|连接的单条检索式
        nList = [x for x in range(len(text)) if regex.search(text[x])]
        return nList

    def extract2(self, text, nList, regex):
        nList = [x for x in nList if regex.search(text[x])]
        return nList

    def not_extract(self, text, nList, regex):
        nList = [x for x in nList if not regex.search(text[x])]
        return nList

    #主函数
    def main(self, path_input, path_output, punc, rule, backward, forward):


        #初始化输出文件
        with open(path_output, "w",
                encoding="utf-8") as f:
                f.write('filename,id,content\n')

        #获取检索规则
        ruleList = rule.split("\n")[:-1]
        if "NOT" in ruleList[-1]:
            outRule = ruleList[-1][3:]
            ruleList.pop()
        else:
            outRule = None

        #读取待检索文件列表并筛选(如有)

        file_list = [
            x for x in os.listdir(path_input) if x.split(".")[-1] == "txt"
        ]

        re_punc = re.compile(r'%s' % punc)
        reList = [re.compile(r'%s' % x) for x in ruleList]
        if outRule!=None:
            re_out=re.compile(r'%s' % outRule)

        #主循环
        for k in range(len(file_list)):

            each = file_list[k]

            #读取文件名
            filename = each[:-4]

            try:
                with open(os.path.join(path_input, each), encoding="gbk") as f:
                    source = f.read()
            except:
                with open(
                        os.path.join(path_input, each),
                        encoding="utf-8",
                        errors="ignore") as f:
                    source = f.read()

            #调用检索函数
            text = re_punc.split(source)
            for i in range(len(reList)):
                if i == 0:
                    nList = self.extract(text, reList[i])
                else:
                    nList = self.extract2(text, nList, reList[i])
            if outRule != None:
                nList = self.not_extract(text, nList, re_out)

            results=[]
            for i in nList:
                start = max(0, i - backward)
                end = min(i + 1 + forward, len(text))
                result = "//".join(text[start:end])
                #result = result.replace(",", "")
                result = result.replace('"',"'")
                result = result.replace("\n", "/")
                results.append(result)

            #结果输出
            with open(
                    path_output, "a",
                    encoding="utf-8") as f:
                if len(results) == 0:
                    f.write(filename)
                    f.write(',')
                    f.write(str(0))
                    f.write(',')
                    f.write('\n')
                else:
                    for j in range(len(results)):
                        f.write(filename)
                        f.write(',')
                        f.write(str(j + 1))
                        f.write(',')
                        f.write('"'+results[j]+'"')
                        f.write('\n')
            print("Processing {} in {}".format(k+1, len(file_list)))
            self.PROG.set(int(100*((k+1)/len(file_list))))
        print("Finished!")


if __name__ == "__main__":
    app = App()
    app.master.title("Extarct6.0Beta")
    app.mainloop()
